/*@internal*/
namespace ts {
    export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, file: SourceFile | undefined): DiagnosticWithLocation[] | undefined {
        const compilerOptions = host.getCompilerOptions();
        const result = transformNodes(resolver, host, compilerOptions, file ? [file] : host.getSourceFiles(), [transformDeclarations], /*allowDtsFiles*/ false);
        return result.diagnostics;
    }

    function hasInternalAnnotation(range: CommentRange, currentSourceFile: SourceFile) {
        const comment = currentSourceFile.text.substring(range.pos, range.end);
        return stringContains(comment, "@内部");
    }

    export function isInternalDeclaration(node: Node, currentSourceFile: SourceFile) {
        const parseTreeNode = getParseTreeNode(node);
        if (parseTreeNode && parseTreeNode.kind === SyntaxKind.Parameter) {
            const paramIdx = (parseTreeNode.parent as FunctionLike).parameters.indexOf(parseTreeNode as ParameterDeclaration);
            const previousSibling = paramIdx > 0 ? (parseTreeNode.parent as FunctionLike).parameters[paramIdx - 1] : undefined;
            const text = currentSourceFile.text;
            const commentRanges = previousSibling
                ? concatenate(
                    // to handle
                    // ... parameters, /* @internal */
                    // public param: string
                    getTrailingCommentRanges(text, skipTrivia(text, previousSibling.end + 1, /* stopAfterLineBreak */ false, /* stopAtComments */ true)),
                    getLeadingCommentRanges(text, node.pos)
                )
                : getTrailingCommentRanges(text, skipTrivia(text, node.pos, /* stopAfterLineBreak */ false, /* stopAtComments */ true));
            return commentRanges && commentRanges.length && hasInternalAnnotation(last(commentRanges), currentSourceFile);
        }
        const leadingCommentRanges = parseTreeNode && getLeadingCommentRangesOfNode(parseTreeNode, currentSourceFile);
        return !!forEach(leadingCommentRanges, range => {
            return hasInternalAnnotation(range, currentSourceFile);
        });
    }

    const declarationEmitNodeBuilderFlags =
        NodeBuilderFlags.MultilineObjectLiterals |
        NodeBuilderFlags.WriteClassExpressionAsTypeLiteral |
        NodeBuilderFlags.UseTypeOfFunction |
        NodeBuilderFlags.UseStructuralFallback |
        NodeBuilderFlags.GenerateNamesForShadowedTypeParams |
        NodeBuilderFlags.NoTruncation;

    /**
     * Transforms a ts file into a .d.ts file
     * This process requires type information, which is retrieved through the emit resolver. Because of this,
     * in many places this transformer assumes it will be operating on parse tree nodes directly.
     * This means that _no transforms should be allowed to occur before this one_.
     */
    export function transformDeclarations(context: TransformationContext) {
        const throwDiagnostic = () => Debug.fail("Diagnostic emitted without context");
        let getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic = throwDiagnostic;
        let isBundledEmit = false;
        let enclosingDeclaration: Node;
        let necessaryTypeReferences: Map<true> | undefined;
        let lateMarkedStatements: LateVisibilityPaintedStatement[] | undefined;
        let suppressNewDiagnosticContexts: boolean;
        let exportedModulesFromDeclarationEmit: Symbol[] | undefined;

        const host = context.getEmitHost();
        const symbolTracker: SymbolTracker = {
            trackSymbol,
            reportInaccessibleThisError,
            reportInaccessibleUniqueSymbolError,
            reportPrivateInBaseOfClassExpression,
            reportLikelyUnsafeImportRequiredError,
            moduleResolverHost: host,
            trackExternalModuleSymbolOfImportTypeNode
        };
        let errorNameNode: DeclarationName | undefined;

        const resolver = context.getEmitResolver();
        return transformRoot;

        function recordTypeReferenceDirectivesIfNecessary(typeReferenceDirectives: readonly string[] | undefined): void {
            if (!typeReferenceDirectives) {
                return;
            }
            necessaryTypeReferences = necessaryTypeReferences || createMap<true>();
            for (const ref of typeReferenceDirectives) {
                necessaryTypeReferences.set(ref, true);
            }
        }

        function handleSymbolAccessibilityError(symbolAccessibilityResult: SymbolAccessibilityResult) {
            if (symbolAccessibilityResult.accessibility === SymbolAccessibility.Accessible) {
                // Add aliases back onto the possible imports list if they're not there so we can try them again with updated visibility info
                if (symbolAccessibilityResult && symbolAccessibilityResult.aliasesToMakeVisible) {
                    if (!lateMarkedStatements) {
                        lateMarkedStatements = symbolAccessibilityResult.aliasesToMakeVisible;
                    }
                    else {
                        for (const ref of symbolAccessibilityResult.aliasesToMakeVisible) {
                            pushIfUnique(lateMarkedStatements, ref);
                        }
                    }
                }

                // TODO: Do all these accessibility checks inside/after the first pass in the checker when declarations are enabled, if possible
            }
            else {
                // Report error
                const errorInfo = getSymbolAccessibilityDiagnostic(symbolAccessibilityResult);
                if (errorInfo) {
                    if (errorInfo.typeName) {
                        context.addDiagnostic(createDiagnosticForNode(symbolAccessibilityResult.errorNode || errorInfo.errorNode,
                            errorInfo.diagnosticMessage,
                            getTextOfNode(errorInfo.typeName),
                            symbolAccessibilityResult.errorSymbolName,
                            symbolAccessibilityResult.errorModuleName));
                    }
                    else {
                        context.addDiagnostic(createDiagnosticForNode(symbolAccessibilityResult.errorNode || errorInfo.errorNode,
                            errorInfo.diagnosticMessage,
                            symbolAccessibilityResult.errorSymbolName,
                            symbolAccessibilityResult.errorModuleName));
                    }
                }
            }
        }

        function trackExternalModuleSymbolOfImportTypeNode(symbol: Symbol) {
            if (!isBundledEmit) {
                (exportedModulesFromDeclarationEmit || (exportedModulesFromDeclarationEmit = [])).push(symbol);
            }
        }

        function trackSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags) {
            if (symbol.flags & SymbolFlags.TypeParameter) return;
            handleSymbolAccessibilityError(resolver.isSymbolAccessible(symbol, enclosingDeclaration, meaning, /*shouldComputeAliasesToMakeVisible*/ true));
            recordTypeReferenceDirectivesIfNecessary(resolver.getTypeReferenceDirectivesForSymbol(symbol, meaning));
        }

        function reportPrivateInBaseOfClassExpression(propertyName: string) {
            if (errorNameNode) {
                context.addDiagnostic(
                    createDiagnosticForNode(errorNameNode, Diagnostics.Property_0_of_exported_class_expression_may_not_be_private_or_protected, propertyName));
            }
        }

        function reportInaccessibleUniqueSymbolError() {
            if (errorNameNode) {
                context.addDiagnostic(createDiagnosticForNode(errorNameNode, Diagnostics.The_inferred_type_of_0_references_an_inaccessible_1_type_A_type_annotation_is_necessary,
                    declarationNameToString(errorNameNode),
                    "unique symbol"));
            }
        }

        function reportInaccessibleThisError() {
            if (errorNameNode) {
                context.addDiagnostic(createDiagnosticForNode(errorNameNode, Diagnostics.The_inferred_type_of_0_references_an_inaccessible_1_type_A_type_annotation_is_necessary,
                    declarationNameToString(errorNameNode),
                    "this"));
            }
        }

        function reportLikelyUnsafeImportRequiredError(specifier: string) {
            if (errorNameNode) {
                context.addDiagnostic(createDiagnosticForNode(errorNameNode, Diagnostics.The_inferred_type_of_0_cannot_be_named_without_a_reference_to_1_This_is_likely_not_portable_A_type_annotation_is_necessary,
                    declarationNameToString(errorNameNode),
                    specifier));
            }
        }

        function transformRoot(node: Bundle): Bundle;
        function transformRoot(node: SourceFile): SourceFile;
        function transformRoot(node: SourceFile | Bundle): SourceFile | Bundle;
        function transformRoot(node: SourceFile | Bundle) {
            if (node.kind === SyntaxKind.SourceFile && node.isDeclarationFile) {
                return node;
            }

            if (node.kind === SyntaxKind.Bundle) {
                isBundledEmit = true;
                let hasNoDefaultLib = false;
                const bundle = createBundle(map(node.sourceFiles,
                    sourceFile => {
                        if (sourceFile.isDeclarationFile) return undefined!; // Omit declaration files from bundle results, too // TODO: GH#18217
                        enclosingDeclaration = sourceFile;
                        lateMarkedStatements = undefined;
                        suppressNewDiagnosticContexts = false;
                        getSymbolAccessibilityDiagnostic = throwDiagnostic;
                        const updated = visitNodes(sourceFile.statements, 访问程序集语句);
                        return updateSourceFileNode(sourceFile, updated, /*isDeclarationFile*/ true);
                    }
                ), 
                mapDefined(node.prepends, prepend => {
                    if (prepend.kind === SyntaxKind.InputFiles) {
                        const sourceFile = createUnparsedSourceFile(prepend, "dk");
                        return sourceFile;
                    }
                    return prepend;
                }));
                bundle.hasNoDefaultLib = hasNoDefaultLib;
                return bundle;
            }

            enclosingDeclaration = node;
            getSymbolAccessibilityDiagnostic = throwDiagnostic;
            isBundledEmit = false;
            suppressNewDiagnosticContexts = false;
            lateMarkedStatements = undefined;
            necessaryTypeReferences = undefined;
            let combinedStatements: NodeArray<Statement>;
            const statements = visitNodes(node.statements, transformTopLevelDeclaration);
            combinedStatements = setTextRange(createNodeArray(statements), node.statements);
            const updated = updateSourceFileNode(node, combinedStatements, /*isDeclarationFile*/ true);
            updated.exportedModulesFromDeclarationEmit = exportedModulesFromDeclarationEmit;
            return updated;
        }

        function filterBindingPatternInitializers(name: BindingName) {
            if (name.kind === SyntaxKind.Identifier) {
                return name;
            }
        }

        function ensureParameter(p: ParameterDeclaration, type?: TypeNode): ParameterDeclaration {
            let oldDiag: typeof getSymbolAccessibilityDiagnostic | undefined;
            if (!suppressNewDiagnosticContexts) {
                oldDiag = getSymbolAccessibilityDiagnostic;
                getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(p);
            }
            const newParam = updateParameter(
                p,
                filterBindingPatternInitializers(p.name)!,
                resolver.isOptionalParameter(p) ? (p.questionToken || createToken(SyntaxKind.QuestionToken)) : undefined,
                ensureType(p, type || p.type), // Ignore private param props, since this type is going straight back into a param
                undefined
            );
            if (!suppressNewDiagnosticContexts) {
                getSymbolAccessibilityDiagnostic = oldDiag!;
            }
            return newParam;
        }

        type HasInferredType =
            | FunctionDeclaration
            | MethodDeclaration
            | VariableDeclaration
            | MethodSignature
            | 内部方法声明_
            | ParameterDeclaration
            | PropertyDeclaration
            | PropertySignature;

        function ensureType(node: HasInferredType, type: TypeNode | undefined): TypeNode | undefined {
            const shouldUseResolverType = node.kind === SyntaxKind.Parameter && (resolver.isRequiredInitializedParameter(node) || resolver.isOptionalUninitializedParameterProperty(node));
            if (type && !shouldUseResolverType) {
                return visitNode(type, visitDeclarationSubtree);
            }
            if (!getParseTreeNode(node)) {
                return type ? visitNode(type, visitDeclarationSubtree) : createKeywordTypeNode(SyntaxKind.AnyKeyword);
            }
            errorNameNode = node.name;
            let oldDiag: typeof getSymbolAccessibilityDiagnostic;
            if (!suppressNewDiagnosticContexts) {
                oldDiag = getSymbolAccessibilityDiagnostic;
                getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(node);
            }
            if (node.kind === SyntaxKind.VariableDeclaration) {
                return cleanup(resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker));
            }
            if (node.kind === SyntaxKind.Parameter
                || node.kind === SyntaxKind.PropertyDeclaration
                || node.kind === SyntaxKind.PropertySignature) {
                if (!node.initializer) return cleanup(resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker, shouldUseResolverType));
                return cleanup(resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker, shouldUseResolverType) || resolver.createTypeOfExpression(node.initializer, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker));
            }
            return cleanup(resolver.createReturnTypeOfSignatureDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker));

            function cleanup(returnValue: TypeNode | undefined) {
                errorNameNode = undefined;
                if (!suppressNewDiagnosticContexts) {
                    getSymbolAccessibilityDiagnostic = oldDiag;
                }
                return returnValue || createKeywordTypeNode(SyntaxKind.AnyKeyword);
            }
        }

        function isDeclarationAndNotVisible(node: NamedDeclaration) {
            node = getParseTreeNode(node) as NamedDeclaration;
            switch (node.kind) {
                case SyntaxKind.FunctionDeclaration:
                case SyntaxKind.InterfaceDeclaration:
                case SyntaxKind.对象声明_:
                case SyntaxKind.结构声明_:
                case SyntaxKind.别名声明_:
                case SyntaxKind.类型声明_:
                case SyntaxKind.EnumDeclaration:
                    return !resolver.isDeclarationVisible(node);
                // The following should be doing their own visibility checks based on filtering their members
                case SyntaxKind.VariableDeclaration:
                    return !getBindingNameVisible(node as VariableDeclaration);
                case SyntaxKind.导入声明_:
                case SyntaxKind.导入从声明_:
                    return false;
            }
            return false;
        }

        function getBindingNameVisible(elem: VariableDeclaration | OmittedExpression): boolean {
            if (isOmittedExpression(elem)) {
                return false;
            }
            return resolver.isDeclarationVisible(elem);
        }

        function updateParamsList(params: NodeArray<ParameterDeclaration>) {
            const newParams = map(params, p => ensureParameter(p));
            if (!newParams) {
                return undefined!; // TODO: GH#18217
            }
            return createNodeArray(newParams, params.hasTrailingComma);
        }

        function ensureTypeParams(params: NodeArray<TypeParameterDeclaration> | undefined) {
            return visitNodes(params, visitDeclarationSubtree);
        }

        function isEnclosingDeclaration(node: Node) {
            return isSourceFile(node)
                || isTypeAliasDeclaration(node)
                || 是类型声明节点(node)
                || isInterfaceDeclaration(node)
                || 是对象声明(node)
                || 是结构声明(node)
                || isFunctionLike(node);
        }

        function preserveJsDoc<T extends Node>(updated: T, original: Node): T {
            if (hasJSDocNodes(updated) && hasJSDocNodes(original)) {
                updated.jsDoc = original.jsDoc;
            }
            if (有转换词典节点(updated) && 有转换词典节点(original)) {
                updated.dict = original.dict;
            }
            return setCommentRange(updated, getCommentRange(original));
        }

        function visitDeclarationSubtree(input: Node): VisitResult<Node> {
            if (isDeclaration(input)) {
                if (isDeclarationAndNotVisible(input)) return;
            }

            // Elide implementation signatures from overload sets
            if (isFunctionLike(input) && resolver.isImplementationOfOverload(input)) return;

            let previousEnclosingDeclaration: typeof enclosingDeclaration;
            if (isEnclosingDeclaration(input)) {
                previousEnclosingDeclaration = enclosingDeclaration;
                enclosingDeclaration = input as Declaration;
            }
            const oldDiag = getSymbolAccessibilityDiagnostic;

            // Setup diagnostic-related flags before first potential `cleanup` call, otherwise
            // We'd see a TDZ violation at runtime
            const canProduceDiagnostic = canProduceDiagnostics(input);
            const oldWithinObjectLiteralType = suppressNewDiagnosticContexts;
            let shouldEnterSuppressNewDiagnosticsContextContext = ((input.kind === SyntaxKind.TypeLiteral) && input.parent.kind !== SyntaxKind.别名声明_);


            if (canProduceDiagnostic && !suppressNewDiagnosticContexts) {
                getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(input as DeclarationDiagnosticProducing);
            }

            if (shouldEnterSuppressNewDiagnosticsContextContext) {
                // We stop making new diagnostic contexts within object literal types. Unless it's an object type on the RHS of a type alias declaration. Then we do.
                suppressNewDiagnosticContexts = true;
            }

            if (isProcessedComponent(input)) {
                switch (input.kind) {
                    case SyntaxKind.ExpressionWithTypeArguments: {
                        const node = visitEachChild(input, visitDeclarationSubtree, context);
                        return node
                    }
                    case SyntaxKind.TypeReference: {
                        const node = visitEachChild(input, visitDeclarationSubtree, context);
                        return node
                    }
                    case SyntaxKind.PropertyDeclaration:
                        return cleanup(updateProperty(
                            input,
                            input.name,
                            input.questionToken,
                            ensureType(input, undefined),
                            undefined
                        ));
                    case SyntaxKind.PropertySignature:
                        return cleanup(updatePropertySignature(
                            input,
                            input.name,
                            input.questionToken,
                            ensureType(input, undefined),
                            undefined
                        ));
                    case SyntaxKind.内部方法声明_:
                        return cleanup(更新内部方法(
                            input,
                            input.name,
                            input.questionToken,
                            ensureTypeParams(input.typeParameters),
                            updateParamsList(createNodeArray(input.parameters.slice(1))),
                            ensureType(input, undefined),
                            undefined,
                        ));

                    case SyntaxKind.MethodSignature: {
                        return cleanup(updateMethodSignature(
                            input,
                            ensureTypeParams(input.typeParameters),
                            updateParamsList(input.parameters),
                            ensureType(input, undefined),
                            input.name,
                            input.questionToken
                        ));
                    }
                    case SyntaxKind.VariableDeclaration: {
                        shouldEnterSuppressNewDiagnosticsContextContext = true;
                        suppressNewDiagnosticContexts = true; // Variable declaration types also suppress new diagnostic contexts, provided the contexts wouldn't be made for binding pattern types
                        return cleanup(updateVariableDeclaration(input, input.name, ensureType(input, undefined), undefined));
                    }
                    case SyntaxKind.TypeParameter: {
                        return cleanup(visitEachChild(input, visitDeclarationSubtree, context));
                    }
                    case SyntaxKind.FunctionType: {
                        return cleanup(updateFunctionTypeNode(input, visitNodes(input.typeParameters, visitDeclarationSubtree), updateParamsList(input.parameters), visitNode(input.type, visitDeclarationSubtree)));
                    }
                    default: Debug.assertNever(input, `Attempted to process unhandled node kind: ${(ts as any).SyntaxKind[(input as any).kind]}`);
                }
            }

            return cleanup(visitEachChild(input, visitDeclarationSubtree, context));

            function cleanup<T extends Node>(returnValue: T | undefined): T | undefined {
                if (isEnclosingDeclaration(input)) {
                    enclosingDeclaration = previousEnclosingDeclaration;
                }
                if (canProduceDiagnostic && !suppressNewDiagnosticContexts) {
                    getSymbolAccessibilityDiagnostic = oldDiag;
                }
                if (shouldEnterSuppressNewDiagnosticsContextContext) {
                    suppressNewDiagnosticContexts = oldWithinObjectLiteralType;
                }
                if (returnValue === input) {
                    return returnValue;
                }
                return returnValue && setOriginalNode(preserveJsDoc(returnValue, input), input);
            }
        }

        type 程序集语句_ =
            | VariableStatement
            | FunctionDeclaration
            | MethodDeclaration
            | 对象声明_
            | 结构声明_
            | 别名声明节点_
            | 类型声明节点_
            | InterfaceDeclaration
            | EnumDeclaration
            | 版本语句_
            | 版本表达式语句_

        function 访问程序集语句(input: 程序集语句_): VisitResult<Node> {
            return 转换程序集语句(input);
        }

        function 转换程序集语句(input: 程序集语句_) {

            let previousEnclosingDeclaration: typeof enclosingDeclaration;
            if (isEnclosingDeclaration(input)) {
                previousEnclosingDeclaration = enclosingDeclaration;
                enclosingDeclaration = input as Declaration;
            }

            const canProdiceDiagnostic = canProduceDiagnostics(input);
            const oldDiag = getSymbolAccessibilityDiagnostic;
            if (canProdiceDiagnostic) {
                getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(input as DeclarationDiagnosticProducing);
            }
            switch (input.kind) {
                case SyntaxKind.VariableStatement:
                    return transformVariableStatement(input);
                case SyntaxKind.FunctionDeclaration:
                    return cleanup(updateFunctionDeclaration(input, input.name, ensureTypeParams(input.typeParameters), updateParamsList(input.parameters), ensureType(input, input.type), undefined));               
                case SyntaxKind.MethodDeclaration:
                    return cleanup(updateMethod(input, input.接受者, input.name, input.questionToken, ensureTypeParams(input.typeParameters), updateParamsList(input.parameters), ensureType(input, input.type), undefined));
                case SyntaxKind.别名声明_:
                    return cleanup(updateTypeAliasDeclaration(
                        input,
                        input.name,
                        visitNodes(input.typeParameters, visitDeclarationSubtree, isTypeParameterDeclaration),
                        visitNode(input.type, visitDeclarationSubtree, isTypeNode)
                    ));
                case SyntaxKind.类型声明_:
                    return cleanup(更新声明类型节点(
                        input,
                        input.name,
                        visitNodes(input.typeParameters, visitDeclarationSubtree, isTypeParameterDeclaration),
                        visitNode(input.type, visitDeclarationSubtree, isTypeNode),
                        visitNodes(input.members, visitDeclarationSubtree, 是内部方法声明)
                    ));
                case SyntaxKind.EnumDeclaration:{
                    return cleanup(updateEnumDeclaration(input, input.name, createNodeArray(mapDefined(input.members, m => {
                        const constValue = resolver.getConstantValue(m);
                        return preserveJsDoc(updateEnumMember(m, m.name, constValue !== undefined ? createLiteral(constValue) : undefined), m);
                    }))));
                }
                case SyntaxKind.InterfaceDeclaration:
                    return cleanup(updateInterfaceDeclaration(input, input.name, ensureTypeParams(input.typeParameters), transformHeritageClauses(input.heritageClauses), visitNodes(input.members, visitDeclarationSubtree)))
                case SyntaxKind.对象声明_:
                    return cleanup(更新对象声明(input, input.name, ensureTypeParams(input.typeParameters), transformHeritageClauses(input.heritageClauses), visitNodes(input.members, visitDeclarationSubtree)));
                case SyntaxKind.结构声明_:
                    return cleanup(更新结构声明(input, input.name, ensureTypeParams(input.typeParameters), visitNodes(input.members, visitDeclarationSubtree)));
                case SyntaxKind.版本语句_:
                    const thenStatement = createBlock(visitNodes(input.thenStatement.statements, visitDeclarationSubtree), true);
                    let elseStatement: Statement | undefined
                    if (input.elseStatement) {
                        if (isBlock(input.elseStatement)) {
                            elseStatement = createBlock(visitNodes(input.elseStatement!.statements, visitDeclarationSubtree), true);
                        }
                        else {
                            elseStatement = visitNode(input.elseStatement, visitDeclarationSubtree);
                        }
                    }
                    return cleanup(更新版本语句(input, input.expression, thenStatement, elseStatement));
                case SyntaxKind.版本表达式语句_:
                    return cleanup(更新版本表达式语句(input, input.expression));
                    default:
                    Debug.assertNever(input);
            }
            function cleanup<T extends Node>(node: T | undefined): T | undefined {
                if (isEnclosingDeclaration(input)) {
                    enclosingDeclaration = previousEnclosingDeclaration;
                }
                if (canProdiceDiagnostic) {
                    getSymbolAccessibilityDiagnostic = oldDiag;
                }
                if (node as Node === input) {
                    return node;
                }
                return node && setOriginalNode(preserveJsDoc(node, input), input);
            }
        }

        function transformTopLevelDeclaration(input: LateVisibilityPaintedStatement) {            
            
            let previousEnclosingDeclaration: typeof enclosingDeclaration;
            if (isEnclosingDeclaration(input)) {
                previousEnclosingDeclaration = enclosingDeclaration;
                enclosingDeclaration = input as Declaration;
            }

            const canProdiceDiagnostic = canProduceDiagnostics(input);
            const oldDiag = getSymbolAccessibilityDiagnostic;
            if (canProdiceDiagnostic) {
                getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(input as DeclarationDiagnosticProducing);
            }

            switch (input.kind) {
                case SyntaxKind.导入从声明_:
                case SyntaxKind.导入声明_:
                    return cleanup(input);
                case SyntaxKind.程序声明_:
                    return cleanup(更新程序声明(input, input.name, visitNodes(input.statements, 访问程序集语句)));
            }

            function cleanup<T extends Node>(node: T | undefined): T | undefined {
                if (isEnclosingDeclaration(input)) {
                    enclosingDeclaration = previousEnclosingDeclaration;
                }
                if (canProdiceDiagnostic) {
                    getSymbolAccessibilityDiagnostic = oldDiag;
                }
                if (node as Node === input) {
                    return node;
                }
                return node && setOriginalNode(preserveJsDoc(node, input), input);
            }
        }

        function transformVariableStatement(input: VariableStatement) {
            if (!forEach(input.declarationList.declarations, getBindingNameVisible)) return;
            const nodes = visitNodes(input.declarationList.declarations, visitDeclarationSubtree);
            if (!length(nodes)) return;
            return updateVariableStatement(input, updateVariableDeclarationList(input.declarationList, nodes));
        }

        function transformHeritageClauses(nodes: NodeArray<HeritageClause> | undefined) {
            return createNodeArray(filter(map(nodes, clause => updateHeritageClause(clause, visitNodes(createNodeArray(filter(clause.types, t => {
                return isEntityNameExpression(t.expression) || (clause.token === SyntaxKind.ColonToken && t.expression.kind === SyntaxKind.NullKeyword);
            })), visitDeclarationSubtree))), clause => clause.types && !!clause.types.length));
        }
    }

    type ProcessedComponent =
        | PropertyDeclaration
        | PropertySignature
        | MethodSignature
        | VariableDeclaration
        | TypeParameterDeclaration
        | ExpressionWithTypeArguments
        | TypeReferenceNode
        | 内部方法声明_
        | FunctionTypeNode;

    function isProcessedComponent(node: Node): node is ProcessedComponent {
        switch (node.kind) {
            case SyntaxKind.PropertyDeclaration:
            case SyntaxKind.PropertySignature:
            case SyntaxKind.MethodSignature:
            case SyntaxKind.内部方法声明_:
            case SyntaxKind.CallSignature:
            case SyntaxKind.VariableDeclaration:
            case SyntaxKind.TypeParameter:
            case SyntaxKind.ExpressionWithTypeArguments:
            case SyntaxKind.TypeReference:
            case SyntaxKind.FunctionType:
                return true;
        }
        return false;
    }
}
